use std::cell::RefCell;
use std::rc::{Rc};
use yew::{Reducible, UseReducerHandle};
use yew_hooks::{UseMapHandle, UseSetHandle, UseWebSocketHandle};
use crate::business::websocket::dto::ping_dto::PongResp;
use crate::business::websocket::dto::rpc_data::{ReceiveDataParse, RpcData};
use crate::business::websocket::dto::user_dto::LoginResp;
use crate::business::websocket::send_data::{ImSendData, ImSendDataMsg};

pub struct ImReceiveData {
    use_web_socket_handle: Rc<RefCell<Option<UseWebSocketHandle>>>,
    send_data_set: UseSetHandle<String>,
    receive_data_set: UseSetHandle<String>,
    session: UseMapHandle<String, String>,
    send_data: Rc<RefCell<Option<UseReducerHandle<ImSendData>>>>,
}

/// websocket发送消息事件
pub enum ImReceiveDataMsg {
    ReceiveData(String),
    ReceiveSendDataAndUseWebSocketHandle(UseReducerHandle<ImSendData>, UseWebSocketHandle),
}

impl PartialEq for ImReceiveData {
    fn eq(&self, other: &Self) -> bool {
        self.send_data_set.eq(&other.send_data_set) && self.receive_data_set.eq(&other.receive_data_set)
    }
}

impl Reducible for ImReceiveData {
    type Action = ImReceiveDataMsg;

    fn reduce(self: Rc<Self>, action: Self::Action) -> Rc<Self> {
        match action {
            ImReceiveDataMsg::ReceiveData(content) => {
                log::info!("received data: {:?}", content);
                let receive_data = ReceiveDataParse::parse(content);
                let _path = &receive_data.path;

                log::info!("received data000, data: {:?}", receive_data);

                let version = receive_data.version;
                let local_seq = receive_data.local_seq();
                if version != 0 {
                    let send_data_set = self.send_data_set.clone();
                    let existed = send_data_set.remove(&local_seq);
                    log::info!("send data success: {:?}, is removed: {}", local_seq, existed);
                } else {
                    let t = self.receive_data_set.clone();
                    log::info!("received data1111");
                    t.insert(local_seq);
                    log::info!("received data44444");
                }

                log::info!("send data set size: {}, receive data set size: {}", self.send_data_set.clone().current().len(), self.receive_data_set.clone().current().len());
                do_receive_data(receive_data, self.send_data.clone(), self.session.clone());
                self
            },
            ImReceiveDataMsg::ReceiveSendDataAndUseWebSocketHandle(send_data, use_web_socket_handle) => {
                self.send_data.borrow_mut().replace(send_data);
                self.use_web_socket_handle.borrow_mut().replace(use_web_socket_handle);
                self
            }
        }
    }
}

fn do_receive_data(receive_data: ReceiveDataParse, send_data: Rc<RefCell<Option<UseReducerHandle<ImSendData>>>>, session: UseMapHandle<String, String>) {
    let path = receive_data.path.clone();
    log::info!("do router: {:?}", path);

    // let receive_data = ReceiveData::parse(receive_data);
    // log::info!("do router000000000000");
    // if let Some(receive_data) = receive_data {
    //     match receive_data {
    //         _=> {
    //             todo!()
    //         }
    //     }
    // } else {
    //     log::info!("no router: {:?}", path);
    // }

}

impl ImReceiveData {
    pub fn new(send_data_set: UseSetHandle<String>,
               receive_data_set: UseSetHandle<String>,
               session: UseMapHandle<String, String>) -> Self {
        Self {
            use_web_socket_handle: Rc::new(RefCell::new(None)),
            send_data_set,
            receive_data_set,
            send_data: Rc::new(RefCell::new(None)),
            session,
        }
    }
}

fn dispatch_send_data(content: String, send_data: Option<UseReducerHandle<ImSendData>>) {
    if let Some(send_data) = send_data {
        log::info!("router dispatch send data: {}", content);
        send_data.dispatch(ImSendDataMsg::SendData(content));
    }
}

fn do_login_response(rpc_data: RpcData<LoginResp>, send_data: Rc<RefCell<Option<UseReducerHandle<ImSendData>>>>, session: UseMapHandle<String, String>) {
    let login_result = &(rpc_data.data.clone().unwrap());
    match login_result {
        Ok(login_resp) => {
            login_success(session, login_resp);
        }
        Err(_) => {}
    }

    let send_data = send_data.borrow().clone();
    if let Some(send_data) = send_data {
        send_data.dispatch(ImSendDataMsg::LoginSuccess(rpc_data));
    }
}

fn login_success(session: UseMapHandle<String, String>, login_resp: &LoginResp) {
    log::info!("router login success: {:?}", login_resp);
    session.insert("authCode".to_string(), login_resp.auth_code.to_string());
    session.insert("AUTH_TOKEN".to_string(), login_resp.auth_token.clone());
    session.insert("TENANT_ID".to_string(), login_resp.tenant_code.clone());
    session.insert("LOGIN_USER_ID".to_string(), login_resp.user_id.clone());
}

